package common

import (
	"encoding/json"
	"fmt"
	"gitee.com/jamon/espoir_go/logger"
	"strconv"
	"strings"
)

const (
	PROTO_WEBSOCKET = uint8(0) // websocket
	PROTO_KCP       = uint8(1) // kcp
)

type MsgRequest struct {
	MsgId uint32          `json:"msg_id"`
	Seq   int32           `json:"seq"` // 消息序号，用于客户端识别消息顺序
	Type  uint32          `json:"type"`
	Data  json.RawMessage `json:"data"`

	From      string
	To        string
	SessionID string // proxy_id_seq, 如 proxy_1_1,
}

func (req *MsgRequest) String() string {
	return fmt.Sprintf("MsgRequest{MsgId: %v, Seq: %v, Type: %v, Data: %v, From: %v, To: %v, SessionID: %v}",
		req.MsgId, req.Seq, req.Type, string(req.Data), req.From, req.To, req.SessionID)
}

type PushMsgRequest struct {
	MsgId uint32          `json:"msg_id"`
	Type  uint32          `json:"type"`
	Data  json.RawMessage `json:"data"`

	From       string
	To         string
	IsAll      bool     //	是否发送所有客户端或节点
	SessionIDs []string // proxy_id_seq, 如 proxy_1_1
}

func (req *PushMsgRequest) String() string {
	return fmt.Sprintf("PushMsgRequest{MsgId: %v, Type: %v, Data: %v, From: %v, To: %v, IsAll: %v, SessionIDs: %v}",
		req.MsgId, req.Type, string(req.Data), req.From, req.To, req.IsAll, req.SessionIDs)
}

type InternalNotifyRequest struct {
	MsgId uint32          `json:"msg_id"`
	Type  uint32          `json:"type"`
	Data  json.RawMessage `json:"data"`

	From string
	To   string
}

func (req *InternalNotifyRequest) String() string {
	return fmt.Sprintf("InternalNotifyRequest{MsgId: %v, Type: %v, Data: %v, From: %v, To: %v}",
		req.MsgId, req.Type, string(req.Data), req.From, req.To)
}

func ParseSessionID(sessionID string) (proxyNum uint32, seq uint32, err error) {
	items := strings.Split(sessionID, "_")
	if len(items) != 3 {
		logger.Error("ParseSessionID: invalid session id: ", logger.Kwargs{"session_id": sessionID})
		return 0, 0, fmt.Errorf("invalid session id: %v", sessionID)
	}
	proxyN, err := strconv.ParseUint(items[1], 10, 32)
	seqN, err2 := strconv.ParseUint(items[2], 10, 32)
	if err != nil || err2 != nil {
		logger.Error("ParseSessionID: invalid session id: ", logger.Kwargs{"session_id": sessionID})
		return 0, 0, fmt.Errorf("invalid session id: %v", sessionID)
	}

	return uint32(proxyN), uint32(seqN), nil
}

func GetProxyID(sessionID string) string {
	items := strings.Split(sessionID, "_")
	if len(items) != 3 {
		return ""
	}
	return fmt.Sprintf("%v_%v", items[0], items[1])
}

type MsgResponse struct {
	MsgId uint32          `json:"msg_id"`
	Seq   int32           `json:"seq"` // 消息序号，用于客户端识别消息顺序
	Type  uint32          `json:"type"`
	Data  json.RawMessage `json:"data"`
}

func (res *MsgResponse) String() string {
	return fmt.Sprintf("MsgResponse{MsgId: %v, Seq: %v, Type: %v, Data: %v}",
		res.MsgId, res.Seq, res.Type, string(res.Data))
}

// 消息类型
const (
	MsgType_REQUEST         = 1 // 请求
	MsgType_RESPONSE        = 2 // 请求响应
	MsgType_PUSH            = 3 // 推送客户端
	MsgType_INTERNAL_NOTIFY = 4 // 集群内部通知
)

// 消息返回码

const (
	MsgCode_SUCCESS = 200 // 成功
)

type InnerMsgIDs struct {
	LenRange       uint32 `json:"len_range"` // 消息ID = 模块ID*BaseRange + 模块内消息ID
	SwitchNetMsgID uint32 `json:"switch_net_msg_id"`
	FrameSyncMsgID uint32 `json:"frame_sync_msg_id"`
}

// DefaultInnerMsgIDs 默认内部消息ID, 可以被覆盖
var DefaultInnerMsgIDs = InnerMsgIDs{
	LenRange:       1000,
	SwitchNetMsgID: 1004,
	FrameSyncMsgID: 500100,
}
